#! /usr/bin/bash
# -*- coding: utf-8 -*-

import os
import sys
import time
import pickle
import app_global
from collections import deque
from datetime import datetime
from queue import Queue

log=app_global.gLog

class CDataprocPlc():
    def __init__(self, db = None, model=None, kfk_p = None ):
        self.db = db
        self.model=model
        self.kfk_p = kfk_p
        #self.q = deque(maxlen=10)

    # data processor
    def data_proc(self, data, q):
        if self.db == None:
            return

        self.q = q

        try:
            self.q.append(data)
            print("\n###### proc data(size: {},max={}):\n {}".format(len(self.q),self.q.maxlen,data))
            self.proc_trace()
        except Exception as e:
            log.error("plc data proc: {}".format(e))


    def proc_trace(self):

        
        list_result_name = [
            "Leverler inlet manual",
            "Leverler outlet manual",
            "Leverler flexion manual",
            "flmg_mean",#full length maxgap预测期望值
            "fcmg_mean",#full cross maxgap预测期望值
            "flmg_prct_90",#full length maxgap 90%的预测最大范围
            "fcmg_prct_90" #full cross maxgap 90%的预测最大范围
        ]

        list_pre_result = [
            "flmg_mean",#full length maxgap预测期望值
            "fcmg_mean",#full cross maxgap预测期望值
            "flmg_prct_90",#full length maxgap 90%的预测最大范围
            "fcmg_prct_90" #full cross maxgap 90%的预测最大范围
        ]

        list_L1_set = [
            "L1_SET_DATA SET_LEVELLER_INLET[mm]",
            "L1_SET_DATA SET_LEVELLER_OUTLET [mm]"
        ]

        #log.info("proc_trace... {}".format(len(global_var.gl_dq_last)))

        tm_now = datetime.now()
        model_param = {"type":1,"option1":2,"option2":1,"thickness":0.5} #模型宽展参数
        
        # 初始化时，没有数据，插入当前数据
        
        if len(app_global.gl_dq_last) == 0:
            log.info("init global deque plate data...")
            plate_data = {}
            plate_data["_id"] = tm_now.strftime("%Y-%m-%d %H:%M:%S")
            plate_data["plate_id"] = self.q[-1]["plate_id"]
            plate_data["material_id"] = self.q[-1]["material_id"]
            plate_data["steel_grade"] = self.q[-1]["steel grade"]
            plate_data["length"] = self.q[-1]["plate length"]
            plate_data["width"] = self.q[-1]["plate width"]
            plate_data["thickness"] = self.q[-1]["plate thickness"]
            plate_data["temp"] = self.q[-1]["plate act temperature"]

            set_val = self.model.calc_model(self.q[-1],model_param)
            if len(set_val):
                ###
                plate_data["set_inlet"] = set_val["Leverler inlet manual"]
                plate_data["set_outlet"] = set_val["Leverler outlet manual"]
                plate_data["set_flexion"]=set_val["Leverler flexion manual"]
                
                if self.kfk_p:
                    log.info("...send set data to kfkfa....")
                    plc_data = [
                    {"db":9000,"stx":0,"value":plate_data["set_inlet"]},
                    {"db":9000,"stx":4,"value":plate_data["set_outlet"]},
                    {"db":9000,"stx":8,"value":plate_data["set_flexion"]},
                                   ]

                    send_data = pickle.dumps(plc_data)
                    self.kfk_p.send('data_set', key = b'set_test', value = send_data)
                # send plc set value @20200318

            
            app_global.gl_dq_last.append(plate_data)


        if len(self.q)<2:
            log.info("self.q(type: {}) size < 2".format(type(self.q)))
            print("return ...")
            return

        #calc 1, new plate
        if self.q[-1]["plate_id"]!= self.q[-2]["plate_id"]:
            #start calc1 set-value
            #todo
            #calc1
            #push data for gl_dq_last
            log.info("****** start calc1")
            plate_data = {}
            plate_data["_id"] = tm_now.strftime("%Y-%m-%d %H:%M:%S")
            plate_data["plate_id"] = self.q[-1]["plate_id"]
            plate_data["material_id"] = self.q[-1]["material_id"]
            plate_data["steel_grade"] = self.q[-1]["steel grade"]
            plate_data["length"] = self.q[-1]["plate length"]
            plate_data["width"] = self.q[-1]["plate width"]
            plate_data["thickness"] = self.q[-1]["plate thickness"]
            plate_data["temp"] = self.q[-1]["plate act temperature"]

            #calc_plateid=self.q[-1]["plate_id"]

            # use model calculate
            set_val = self.model.calc_model(self.q[-1],model_param)
            
            
            #save plate data            
            if len(set_val):
                ###
                plate_data["set_inlet"] = set_val["Leverler inlet manual"]
                plate_data["set_outlet"] = set_val["Leverler outlet manual"]
                plate_data["set_flexion"]=set_val["Leverler flexion manual"]
                #send message to kafka

                if self.kfk_p:
                    log.info("...send cal1 data to kfkfa....")
                    plc_data = [
                    {"db":9000,"stx":0,"value":plate_data["set_inlet"]},
                    {"db":9000,"stx":4,"value":plate_data["set_outlet"]},
                    {"db":9000,"stx":8,"value":plate_data["set_flexion"]},
                                   ]

                    send_data = pickle.dumps(plc_data)
                    self.kfk_p.send('data_set', key = b'set_data', value = send_data)
                ###
                sav_values = {}
                sav_values["ctime"] = tm_now
                sav_values.update(self.q[-1].copy()) 
                sav_values_ext = {}
                for _it in list_result_name:
                    sav_values_ext["1st {}".format(_it)] = set_val[_it]
                
                sav_values.update(sav_values_ext)

                oids = self.db.insert(BASE_TABLE,sav_values)
                if len(oids):
                    self.synpd.insert(self.q[-1]["plate_id"], oids[0])
                
                #print(set_val)
            
            
            app_global.gl_dq_last.append(plate_data)

            return

        #calc 2
        if self.q[-1]["Forward mode"]:
            if (self.q[-1]["Before PinchRoll"] and self.q[-1]["Before Leveller"]) and self.q[-2]["Before Leveller"] == 0: 
                #cacl2 the set-value
                #todo
                LINE_STATUS["calc2_on"]=1
                LINE_STATUS["calc2_cd"]=5 #delay 5 times, include the start
                
            if self.q[-1]["Before PinchRoll"] and self.q[-1]["Before Leveller"]:

                if abs(self.q[-2][list_L1_set[0]]) <= 0.0001 and abs(self.q[-1][list_L1_set[0]]) > 0.0001:
                    log.info("L1 Set[{}] {} --> {}".format(list_L1_set[0],self.q[-2][list_L1_set[0]], self.q[-1][list_L1_set[0]]))
                    LINE_STATUS["L1_seton"] = 1

                if LINE_STATUS["calc2_on"] :
                    if LINE_STATUS["calc2_cd"]:
                        LINE_STATUS["calc2_cd"] -= 1
                    else:
                        LINE_STATUS["calc2_on"] = 0
                        log.info("****** start calc 2nd, tm {}".format(type(tm_now)))

                        pass_calc1 = False
                        plate_data={}
                        for _it in global_var.gl_dq_last:
                            if _it["plate_id"] == self.q[-1]["plate_id"]:
                                plate_data = _it
                                pass_calc1 = True
                                break

                        #log.info("##################### {}".format(tm_now.strftime("%Y-%m-%d %H:%M:%S")))
                        
                        #plate_date["_id"] = tm_now.strftime("%Y-%m-%d %H:%M:%S")
                        
                        plate_data["plate_id"] = self.q[-1]["plate_id"]
                        
                        plate_data["material_id"] = self.q[-1]["material_id"]
                        
                        plate_data["steel_grade"] = self.q[-1]["steel grade"]
                        
                        plate_data["length"] = self.q[-1]["plate length"]
                        
                        plate_data["width"] = self.q[-1]["plate width"]
                        
                        plate_data["thickness"] = self.q[-1]["plate thickness"]
                        plate_data["temp"] = self.q[-1]["plate act temperature"]
                       
                        
                        log.info("######## start 2nd calc & pre calc")
                        #start calc2 set-value
                        set_val = self.model.calc_model(self.q[-1],model_param)

                                #用户输入值反算矫直结果

                        model_param["type"] = 0
                        set_val_pre = self.model.calc_model(self.q[-1], model_param)

                        ######################################################
                        # @2020/01/21
                        # record model calc log

                        ######################################################
                        if len(set_val):
                            plate_data["set_inlet"] = set_val["Leverler inlet manual"]
                            plate_data["set_outlet"] = set_val["Leverler outlet manual"]
                            plate_data["set_flexion"]=set_val["Leverler flexion manual"]

                            # send data to kafka
                            if self.kfk_p:
                                log.info("...send cal2 data to kfkfa....")
                                plc_data = [
                                    {"db":9000,"stx":0,"value":plate_data["set_inlet"]},
                                    {"db":9000,"stx":4,"value":plate_data["set_outlet"]},
                                    {"db":9000,"stx":8,"value":plate_data["set_flexion"]},
                                ]

                                send_data = pickle.dumps(plc_data)
                                self.kfk_p.send('data_set', key = b'set_data', value = send_data)

                            sav_values = {}
                            sav_values_ext = {}
                            
                            sav_values.update(self.q[-1].copy())
                            sav_values["recv_shape"] = 0 #是否完成板形数据的采集

                            for _it in list_result_name:
                                sav_values_ext["2nd {}".format(_it)] = set_val[_it]
                            
                            if len(set_val_pre):
                                for _it in list_pre_result:
                                    sav_values_ext["pre {}".format(_it)] = set_val_pre[_it]
                               
                            sav_values.update(sav_values_ext)
                            
                            log.info("pre calc: {}".format(sav_values["pre flmg_mean"]))
                            oid = self.synpd.get_oid(self.q[-1]["plate_id"])
                            log.info("##### get oid: {}".format(oid))
                            if oid:
                                # log.info("update [{}], act temp: {}({}), save fieldnum: {}".format(self.q[-1]["plate_id"],self.q[-1]["plate act temperature"]
                                #                                                        ,sav_values_ext["plate act temperature"],len(sav_values_ext)))
                                # sav_values_ext["plate act temperature"] = self.q[-1]["plate act temperature"]
                                # self.db.update("flattensys",oid,sav_values_ext)
                                # sav_values_up = {}
                                # sav_values_up["ctime"] = datetime.now()
                                # sav_values_up.update(sav_values)
                                log.info("calc2 update data for {}[{}]".format(oid,sav_values["plate_id"]))
                                self.db.update(BASE_TABLE,oid,sav_values)
                                self.synpd.set_state(oid, "calc2")

                            else:
                                sav_value_ins = {}
                                sav_value_ins["ctime"]=tm_now
                                sav_value_ins.update(sav_values)
                                log.info("calc2 insert data for [{}]".format(sav_value_ins["plate_id"]))
                                oids = self.db.insert(BASE_TABLE,sav_value_ins)
                                
                                self.synpd.insert(self.q[-1]["plate_id"], oids[0],"calc2")
                            

                            if not pass_calc1:
                                app_global.gl_dq_last.append(plate_data)

                if LINE_STATUS["L1_seton"]:
                    
                    LINE_STATUS["L1_seton"] = 0
                    try:
                        oid = self.synpd.get_oid(self.q[-1]["plate_id"])
                        if oid:
                            sav_values = {}
                            for _it in list_L1_set:
                                sav_values[_it] = self.q[-1][_it]

                            self.db.update(BASE_TABLE,oid,sav_values)
                            log.info("update L1 set for {},[{:.2f},{:.2f}]".format(self.q[-1]["plate_id"]
                                                                                ,self.q[-1][list_L1_set[0]]
                                                                                ,self.q[-1][list_L1_set[1]]
                                                                                ))
                            #self.synpd.set_state(oid, "calc2")
                    except Exception as e:
                        log.error("err: {}".format(e))
